package export;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.ParseException;
import java.util.List;

import neuron.Coord;
import neuron.Dendrite;
import neuron.Network;
import neuron.Neuron;
import neuron.NeuronFilter;
import neuron.Statistics;
import neuron.file.NeuroLucidaLoader;
import neuron.geometry.Transform;

import matlab.Matlab5File;
import common.statistics.Series;

/**
 * Morphology to matlab export.
 * 
 * @author risto
 * @see NeuronToMatlabExport
 * @see StatisticsToMatlabExport
 *
 */
public class CoordinateToMatlabExport { 
 
	
	private void writeNeuron(Neuron n)
	{
		String filename = (String)n.getMetadata("FILE");
		filename = filename.replaceAll("[_.]", "");

		// collect coordinates
		List<Coord> allCoord = n.getAllBasalCoordinates();
		
		// convert to an array
		double[] arr = new double[3*allCoord.size()];
		for (int i = 0; i < allCoord.size(); i++) {
			arr[3*i+0] = allCoord.get(i).x;
			arr[3*i+1] = allCoord.get(i).y;
			arr[3*i+2] = allCoord.get(i).z;
			if (i == 0) System.out.println("c"+filename + " -> (" + arr[0] + ", " + arr[1] + ", " + arr[2]+")");
		}
		
		// write to matlab
		m5.addDoubleArray("c"+filename, arr, 3, allCoord.size());
	}
	
	Matlab5File m5;
	
	private void coordExport(File datadir, File mat) throws FileNotFoundException, IOException, ParseException 
	{
		// Open matlab
		m5 = new Matlab5File();
		
		File[] files = datadir.listFiles(FileFilters.ascFilter);
//		int nFiles = files.length;
		
		// segment length distributions
		Series basalTermSegLens = new Series();
		Series basalIntSegLens = new Series();
		Series oblTermSegLens = new Series();
		Series oblIntSegLens = new Series();
		Series tuftTermSegLens = new Series();
		Series tuftIntSegLens = new Series();

		// Write data
		for (File f : files) {
			Network net = NeuroLucidaLoader.load(f);
			Neuron n = net.get(0);
			NeuronFilter.filterNeuron(n);
			
			// write coordinates
			Transform.translateToOrigo(n);
			Transform.rotateApicalToYAxis(n);
			Transform.rotateMaxVariation(n);
			writeNeuron(n);
			
			// segment length distributions
			for (Dendrite d : n.basalDendrites()) {
				Statistics stat = new Statistics(d.root);
				basalTermSegLens.merge(stat.terminalSegmentLengths());
				basalIntSegLens.merge(stat.intermediateSegmentLengths());
			}
			for (Dendrite d : n.getApicalDendrite().getObliqueDendrites()) {
				Statistics stat = new Statistics(d.root);
				oblTermSegLens.merge(stat.terminalSegmentLengths());
				oblIntSegLens.merge(stat.intermediateSegmentLengths());
			}
			for (Dendrite d : n.getApicalDendrite().getTuftDendriteAsList()) {
				Statistics stat = new Statistics(d.root);
				tuftTermSegLens.merge(stat.terminalSegmentLengths());
				tuftIntSegLens.merge(stat.intermediateSegmentLengths());
			}
		}		
		
		m5.addDoubleArray("basal_intseg_lengths", basalIntSegLens.values(), basalIntSegLens.count(), 1);
		m5.addDoubleArray("basal_termseg_lengths", basalTermSegLens.values(), basalTermSegLens.count(), 1);

		m5.addDoubleArray("oblique_intseg_lengths", oblIntSegLens.values(), oblIntSegLens.count(), 1);
		m5.addDoubleArray("oblique_termseg_lengths", oblTermSegLens.values(), oblTermSegLens.count(), 1);
		
		m5.addDoubleArray("tuft_intseg_lengths", tuftIntSegLens.values(), tuftIntSegLens.count(), 1);
		m5.addDoubleArray("tuft_termseg_lengths", tuftTermSegLens.values(), tuftTermSegLens.count(), 1);

		
		m5.write(mat);
	}

	public void export(File src, File dest) throws IOException
	{
		if (!src.isDirectory()) throw new IOException("Source has to be directory for CoordinateExport!");
		
		try {
			coordExport(src, dest);
		} catch (Exception ex) {
			throw new IOException(ex);
		}
	}
}
